package com.onlyxiahui.common.utils.base.security;

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * 字符串 DESede(3DES) 加密 
 * ECB模式/使用PKCS7方式填充不足位,目前给的密钥是192位 
 * 3DES（即Triple DES）是DES向AES过渡的加密算法（1999年，NIST将3-DES指定为过渡的 
 * 加密标准），是DES的一个更安全的变形。它以DES为基本模块，通过组合分组方法设计出分组加 
 * 密算法，其具体实现如下：设Ek()和Dk()代表DES算法的加密和解密过程，K代表DES算法使用的 
 * 密钥，P代表明文，C代表密表，这样， 
 * 3DES加密过程为：C=Ek3(Dk2(Ek1(P))) 
 * 3DES解密过程为：P=Dk1((EK2(Dk3(C))) 
 * */
/**
 * 
 * DescriptionDESede(3DES) 加密 <br>
 * Date 2020-11-09 13:47:53<br>
 * 
 * @author XiaHui [onlovexiahui@qq.com]<br>
 * @since 1.0.0
 */
public class Security3DesUtil {

	/**
	 * 
	 * Description 使用3Des算法对报文进行加密<br>
	 * Date 2020-11-09 13:47:21<br>
	 * 
	 * @param keyBytes   加密密钥，定长24位
	 * @param ivBytes    向量，定长8位
	 * @param valueBytes 需要进行加密的报文字节数组
	 * @return
	 * @throws Exception
	 * @since 1.0.0
	 */
	public static byte[] encrypt(byte[] keyBytes, byte[] ivBytes, byte[] valueBytes) throws Exception {
		Key deskey = null;
		DESedeKeySpec spec = new DESedeKeySpec(keyBytes);
		SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
		deskey = keyfactory.generateSecret(spec);
		Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
		IvParameterSpec ips = new IvParameterSpec(ivBytes);
		cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
		byte[] outBytes = cipher.doFinal(valueBytes);
		return outBytes;
	}

	/**
	 * 
	 * Description 解密<br>
	 * Date 2020-11-09 13:49:21<br>
	 * 
	 * @param keyBytes
	 * @param ivBytes
	 * @param valueBytes
	 * @return
	 * @throws Exception
	 * @since 1.0.0
	 */
	public static byte[] decrypt(byte[] keyBytes, byte[] ivBytes, byte[] valueBytes) throws Exception {
		Key deskey = null;
		DESedeKeySpec spec = new DESedeKeySpec(keyBytes);
		SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
		deskey = keyfactory.generateSecret(spec);
		Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
		IvParameterSpec ips = new IvParameterSpec(ivBytes);
		cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
		byte[] bOut = cipher.doFinal(valueBytes);
		return bOut;
	}

	private static final String Algorithm = "DESede"; // 定义加密算法,可用
														// DES,DESede,Blowfish
	// keybyte为加密密钥，长度为24字节
	// src为被加密的数据缓冲区（源）

	public static byte[] encrypt(byte[] keyBytes, byte[] valueBytes) {
		try {
			// 生成密钥
			SecretKey deskey = new SecretKeySpec(keyBytes, Algorithm);
			// 加密
			Cipher cipher = Cipher.getInstance(Algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, deskey);
			return cipher.doFinal(valueBytes);// 在单一方面的加密或解密
		} catch (java.security.NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (java.lang.Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	// keybyte为加密密钥，长度为24字节
	// src为加密后的缓冲区
	public static byte[] decrypt(byte[] keyBytes, byte[] valueBytes) {
		try {
			SecretKey key = new SecretKeySpec(keyBytes, Algorithm); // 生成密钥
			Cipher cipher = Cipher.getInstance(Algorithm);
			cipher.init(Cipher.DECRYPT_MODE, key); // 解密
			return cipher.doFinal(valueBytes);
		} catch (java.security.NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (java.lang.Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
